package cn.utils.excelutil;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zchcpy
 * @date 17
 * excel
 */
public class ExcelUtil {
  /**
   * 总行数
   */
  public int totalRows = 0;
  /**
   * 总列数
   */
  public int totalCells = 0;
  /**
   * 错误信息
   */
  public String errorInfo;
  /**
   * 判断导入Excel表内容格式并输出公用方法-20170822-wxb
   */
  public static String getHSSTextString(Row row, int colNum) {
    Cell cell = row.getCell(colNum);
    if (null != cell) {
      // 以下是判断数据的类型
      switch (cell.getCellType()) {
        case HSSFCell.CELL_TYPE_NUMERIC:
          // 数字
          if (HSSFDateUtil.isCellDateFormatted(cell)) {
            // 如果是date类型则 ，获取该cell的date值
            DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return formater.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
          }
          else {
						/*
						 纯数字 会造成小数被四射五入 180906 zch
						 DecimalFormat df = new DecimalFormat("0.00")
						 return df.format(cell.getNumericCellValue())
						 */
            return new BigDecimal(cell.getNumericCellValue()).toString();
          }
        case HSSFCell.CELL_TYPE_STRING:
          // 字符串
          return cell.getStringCellValue();
        case HSSFCell.CELL_TYPE_BOOLEAN:
          // Boolean
          return cell.getBooleanCellValue() + "";
        case HSSFCell.CELL_TYPE_FORMULA:
          // 公式
          return cell.getCellFormula() + "";
        case HSSFCell.CELL_TYPE_BLANK:
          // 空值
          return "";
        case HSSFCell.CELL_TYPE_ERROR:
          // 故障
          return "非法字符";
        default:
          return "未知类型";
      }
    }
    else {
      return "";
    }
  }
  /**
   * writeToExcel
   */
  public static void writeToExcel(List<List<Object>> valueList, List<?> headList, String sheetName, String logPath) {
    // 第一步，创建一个webbook，对应一个Excel文件
    HSSFWorkbook wb = new HSSFWorkbook();
    // 第二步，在webbook中添加一个sheet,对应Excel文件中的sheet
    HSSFSheet sheet = null;
    if (null == sheetName) {
      sheet = wb.createSheet("sheet1");
    }
    else {
      sheet = wb.createSheet(sheetName);
    }
    // 第三步，在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
    HSSFRow row = sheet.createRow((int) 0);
    // 第四步，创建单元格，并设置值表头 设置表头居中
    HSSFCellStyle style = wb.createCellStyle();
    style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式
    if (null == headList) {
      HSSFCell cell = row.createCell((short) 0);
      cell.setCellValue("列1");
      cell.setCellStyle(style);
      cell = row.createCell((short) 1);
      cell.setCellValue("列2");
      cell.setCellStyle(style);
      cell = row.createCell((short) 2);
      cell.setCellValue("列3");
      cell.setCellStyle(style);
      cell = row.createCell((short) 3);
      cell.setCellValue("列4");
      cell.setCellStyle(style);
    }
    else {
      HSSFCell cell;
      for (int i = 0; i < headList.size(); i++) {
        cell = row.createCell((short) i);
        cell.setCellValue(headList.get(i).toString());
        cell.setCellStyle(style);
      }
    }
    // 第五步，写入实体数据 实际应用中这些数据从数据库得到，
    for (int i = 0; i < valueList.size(); i++) {
      row = sheet.createRow((int) i + 1);
      // 第四步，创建单元格，并设置值
      List<Object> cellList = valueList.get(i);
      for (int j = 0; j < cellList.size(); j++) {
        row.createCell(j).setCellValue(cellList.get(j).toString());
      }
    }
    // 第六步，将文件存到指定位置
    try {
      FileOutputStream fout = new FileOutputStream(logPath);
      wb.write(fout);
      fout.close();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * writeExcelAppend
   */
  public static void writeExcelAppend(String path, int sheetAddr, List<List<Object>> contentList) {
    try {
      // 获取d://test.xls
      FileInputStream fs = new FileInputStream(path);
      if (WDWUtil.isExcel2003(path)) {
        // 使用POI提供的方法得到excel的信息
        POIFSFileSystem ps = new POIFSFileSystem(fs);
        HSSFWorkbook wb = new HSSFWorkbook(ps);
        // 获取到工作表，因为一个excel可能有多个工作表
        HSSFSheet sheet = wb.getSheetAt(sheetAddr);
        // 获取第一行（excel中的行默认从0开始，所以这就是为什么，一个excel必须有字段列头），即，字段列头，便于赋值
        sheet.getRow(0);
        HSSFRow row;
        // 分别得到最后一行的行号，和一条记录的最后一个单元格
        // row.getLastCellNum());
        FileOutputStream out = new FileOutputStream(path); // 向d://test.xls中写数据
        // row=sheet.createRow((short)(sheet.getLastRowNum()+1));
        // //在现有行号后追加数据
        // row.createCell(0).setCellValue("leilei"); //设置第一个（从0开始）单元格的数据
        // row.createCell(1).setCellValue(24); //设置第二个（从0开始）单元格的数据
        // 登录时间 登录名 公司id 远程登录ip1 远程登录ip2 远程登录端口 SessionId
        // 日志日期 机器号 登录名 命令时间 命令
        for (int i = 0; i < contentList.size(); i++) {
          List<Object> cellList = contentList.get(i);
          row = sheet.createRow((short) (sheet.getLastRowNum() + (i + 1)));
          for (int j = 0; j < cellList.size(); j++) {
            row.createCell(j).setCellValue(cellList.get(j).toString());
          }
        }
        out.flush();
        wb.write(out);
        out.close();
      }
      else if (WDWUtil.isExcel2007(path)) {
        XSSFWorkbook wb = new XSSFWorkbook(fs);
        XSSFSheet sheet = wb.getSheetAt(sheetAddr); // 获取到工作表，因为一个excel可能有多个工作表
        XSSFRow row = sheet.getRow(0); // 获取第一行（excel中的行默认从0开始，所以这就是为什么，一个excel必须有字段列头），即，字段列头，便于赋值
        // row.getLastCellNum()); // 分别得到最后一行的行号，和一条记录的最后一个单元格
        FileOutputStream out = new FileOutputStream(path); // 向d://test.xls中写数据
        for (int i = 0; i < contentList.size(); i++) {
          List<Object> cellList = contentList.get(i);
          row = sheet.createRow((short) (sheet.getLastRowNum() + (i + 1)));
          for (int j = 0; j < cellList.size(); j++) {
            row.createCell(j).setCellValue(cellList.get(j).toString().isEmpty());
          }
        }
        out.flush();
        wb.write(out);
        out.close();
      }
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  /**
   * 描述:得到总行数 时间:2014-08-29 下午16:27:15
   * 参数:return
   * 返回值:int
   */
  public int getTotalRows() {
    return totalRows;
  }
  /**
   * 描述:得到总列数 时间:2014-08-29 下午16:27:15
   * 参数:return
   * 返回值:int
   */
  public int getTotalCells() {
    return totalCells;
  }
  /**
   * 描述:得到错误信息 时间:2014-08-29 下午16:27:15
   * 参数:return
   * 返回值:String
   */
  public String getErrorInfo() {
    return errorInfo;
  }
  /**
   * 描述:验证excel文件 时间:2014-08-29 下午16:27:15
   * 参数:param filePath 文件完整路径
   * 参数:return
   * 返回值:boolean
   */
  private boolean validateExcel(String filePath) {
    /*检查文件名是否为空或者是否是Excel格式的文件 */
    if (filePath == null || !(WDWUtil.isExcel2003(filePath) || WDWUtil.isExcel2007(filePath))) {
      errorInfo = "文件名不是excel格式";
      return false;
    }
    /* 检查文件是否存在 */
    File file = new File(filePath);
    if (!file.exists()) {
      errorInfo = "文件不存在";
      return false;
    }
    return true;
  }
  /**
   * 描述:根据文件名读取excel文件 时间:2014-08-29 下午16:27:15
   * 参数:param filePath 文件完整路径
   * 参数:return
   * 返回值:List
   */
  public List<List<Object>> read(String filePath) {
    List<List<Object>> dataLst = new ArrayList<>();
    InputStream is = null;
    try {
      /* 验证文件是否合法 */
      if (!validateExcel(filePath)) {
        return null;
      }
      /* 判断文件的类型，是2003还是2007 */
      boolean isExcel2003 = true;
      if (WDWUtil.isExcel2007(filePath)) {
        isExcel2003 = false;
      }
      /* 调用本类提供的根据流读取的方法 */
      File file = new File(filePath);
      is = new FileInputStream(file);
      dataLst = readExcel(is, isExcel2003);
      is.close();
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
    finally {
      if (is != null) {
        try {
          is.close();
        }
        catch (IOException e) {
          is = null;
          e.printStackTrace();
        }
      }
    }
    /* 返回最后读取的结果 */
    return dataLst;
  }
  /**
   * 描述:根据文件名读取excel文件 时间:2014-08-29 下午16:27:15
   * 参数:param file 文件
   * 参数:return
   * 返回值:List
   */
  public List<List<Object>> read(File file) {
    List<List<Object>> dataLst = new ArrayList<>();
    InputStream is = null;
    try {
      /* 判断文件的类型，是2003还是2007 */
      boolean isExcel2003 = !WDWUtil.isExcel2007(file.getName());
      is = Files.newInputStream(file.toPath());
      dataLst = readExcel(is, isExcel2003);
      is.close();
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
    finally {
      if (is != null) {
        try {
          is.close();
        }
        catch (IOException e) {
          is = null;
          e.printStackTrace();
        }
      }
    }
    /*返回最后读取的结果 */
    return dataLst;
  }
  public List<List<Object>> readExcel(InputStream is, boolean isExcel2003) {
    List<List<Object>> dataLst = null;
    try {
      /* 根据版本选择创建Workbook的方式 */
      Workbook wb;
      if (isExcel2003) {
        wb = new HSSFWorkbook(is);
      }
      else {
        wb = new XSSFWorkbook(is);
      }
      dataLst = doReadExcel(wb);
    }
    catch (IOException e) {
      e.printStackTrace();
    }
    return dataLst;
  }
  public List<List<Object>> doReadExcel(Workbook wb) {
    List<List<Object>> dataLst = new ArrayList<>();
    /* 得到第一个shell */
    Sheet sheet = wb.getSheetAt(0);
    /* 得到Excel的行数 */
    this.totalRows = sheet.getPhysicalNumberOfRows();
    /* 得到Excel的列数 */
    if (this.totalRows >= 1 && sheet.getRow(0) != null) {
      this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
    }
    /* 循环Excel的行 */
    for (int r = 0; r < this.totalRows; r++) {
      Row row = sheet.getRow(r);
      if (row == null) {
        continue;
      }
      List<Object> rowLst = new ArrayList<>();
      /* 循环Excel的列 */
      for (int c = 0; c < this.getTotalCells(); c++) {
        //  Cell cell = row.getCell(c);
        //  if(cell == null){
        //      continue;
        //  }
        //  cell.setCellType(Cell.CELL_TYPE_STRING);
        //  String cellValue = cell.getStringCellValue();
        String cellValue = getHSSTextString(row, c).trim().replaceAll("\\s", "");
        //        if (StringUtils.isEmpty(cellValue)) {
        if (cellValue.isEmpty()) {
          break;
        }
        else {
          rowLst.add(cellValue);
        }
      }
      if (rowLst.size() < 1) {
        break;
      }
      else {
        /* 保存第r行的第c列 */
        dataLst.add(rowLst);
      }
    }
    return dataLst;
  }
  /*-----------------------*/
  /**
   * main
   */
  public static void main(String[] args) {
    // 消除警告用 不能实际运行
  }
}
